/**
 * Copyright 2009 Adam Ruggles.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.google.code.sapien.action;

import java.util.List;

import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Result;
import org.apache.struts2.interceptor.validation.SkipValidation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.code.sapien.interceptor.InputErrorsAware;
import com.google.code.sapien.interceptor.UserAware;
import com.google.code.sapien.model.Category;
import com.google.code.sapien.model.Discussion;
import com.google.code.sapien.model.Response;
import com.google.code.sapien.model.User;
import com.google.code.sapien.service.CategoryService;
import com.google.code.sapien.service.DiscussionService;
import com.google.code.sapien.service.ResponseService;
import com.google.code.sapien.util.PaginatedResult;
import com.google.inject.Inject;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.validator.annotations.RequiredStringValidator;

/**
 * Discussion Action, used to create, update, remove and view discussions.
 * @author Adam
 * @version $Id: DiscussionAction.java 25 2009-05-26 04:23:01Z a.ruggles $
 * 
 * Created on Feb 20, 2009 at 7:36:32 PM 
 */
public class DiscussionAction extends ActionSupport implements UserAware, InputErrorsAware {
	/**
	 * The default number of results per page.
	 */
	public static final int RESULTS_PER_PAGE = 50;

	/**
	 * Serial Version UID.
	 */
	private static final long serialVersionUID = -2760149394321808442L;

	/**
	 * The body of a discussion.
	 */
	private String body;

	/**
	 * A List of categories for displaying in the view.
	 */
	private List<Category> categories;

	/**
	 * The category id.
	 */
	private Long categoryId;

	/**
	 * The category service.
	 */
	private final CategoryService categoryService;

	/**
	 * A discussion object for displaying discussion information in the view.
	 */
	private Discussion discussion;

	/**
	 * The discussion service.
	 */
	private final DiscussionService discussionService;

	/**
	 * The discussion id.
	 */
	private Long id;

	/**
     * The <code>Logger</code> is used by the application to generate a log messages.
     */
    private static final Logger LOG = LoggerFactory.getLogger(DiscussionAction.class);

	/**
	 * The logged in user.
	 */
	private User currentUser;

	/**
	 * The page number.
	 */
	private int page = 1;

	/**
	 * A PaginatedResult of responses.
	 */
	private PaginatedResult<Response> paginatedResult;

	/**
	 * The discussion service.
	 */
	private final ResponseService responseService;

	/**
	 * The subject of a discussion.
	 */
	private String subject;

	/**
	 * Constructs a discussion action.
	 * @param discussionService The discussion service.
	 * @param responseService The response service.
	 * @param categoryService The category service.
	 */
	@Inject
	public DiscussionAction(final DiscussionService discussionService, final ResponseService responseService,
			final CategoryService categoryService) {
		super();
		this.discussionService = discussionService;
		this.responseService = responseService;
		this.categoryService = categoryService;
	}

	/**
	 * Prepares the discussion add page.
	 * @return SUCCESS.
	 */
	@Action("new-discussion")
	@SkipValidation
	public String add() {
		categories = categoryService.getAll();
		return SUCCESS;
	}

	/**
	 * Creates a new discussion.
	 * @return SUCCESS.
	 */
	@Action(value = "create-discussion", results = {
			@Result(name = "input", location = "new-discussion.jsp"),
			@Result(name = "success", location = "discussion.jsp")
			}
	)
	public String create() {
		final Discussion discussion = new Discussion();
		final Category category = new Category();
		final Response response = new Response();
		category.setId(categoryId);
		discussion.setSubject(subject);
		response.setBody(body);
		discussion.setCategory(category);
		discussion.setResponse(response);
		discussionService.add(discussion, currentUser);
		this.setId(discussion.getId());
		addActionMessage(this.getText("create-discussion.success", "The discussion was created successfully."));
		return execute();
	}

	/**
	 * {@inheritDoc}
	 * Loads a discussion and responses for display.
	 * @see com.opensymphony.xwork2.ActionSupport#execute()
	 * @return SUCCESS or ERROR.
	 */
	@Override @SkipValidation
	public String execute() {
		if (id == null) {
			LOG.warn("invalid id recieved when trying to load a discussion");
			return ERROR;
		}
		discussion = discussionService.get(id);
		paginatedResult = responseService.getPage(discussion, page, RESULTS_PER_PAGE);
		categories = categoryService.getAll();
		return SUCCESS;
	}
	/**
	 * Returns body.
	 * @return the body.
	 */
	@RequiredStringValidator(message = "Required Field.", key = "validation.required")
	public String getBody() {
		return body;
	}

	/**
	 * Returns categories.
	 * @return the categories.
	 */
	public List<Category> getCategories() {
		return categories;
	}

	/**
	 * Returns categoryId.
	 * @return the categoryId.
	 */
	public Long getCategoryId() {
		return categoryId;
	}

	/**
	 * Returns discussion.
	 * @return the discussion.
	 */
	public Discussion getDiscussion() {
		return discussion;
	}

	/**
	 * Returns id.
	 * @return the id.
	 */
	public Long getId() {
		return id;
	}

	/**
	 * Returns page.
	 * @return the page.
	 */
	public int getPage() {
		return page;
	}

	/**
	 * Returns paginatedResult.
	 * @return the paginatedResult.
	 */
	public PaginatedResult<Response> getPaginatedResult() {
		return paginatedResult;
	}

	/**
	 * Returns subject.
	 * @return the subject.
	 */
	@RequiredStringValidator(message = "Required Field.", key = "validation.required")
	public String getSubject() {
		return subject;
	}

	/**
	 * {@inheritDoc}
	 * @see com.google.code.sapien.interceptor.InputErrorsAware#prepareInputErrors()
	 */
	public void prepareInputErrors() {
		categories = categoryService.getAll();
	}

	/**
	 * Sets body.
	 * @param body the body to set.
	 */
	public void setBody(final String body) {
		this.body = body;
	}

	/**
	 * Sets categoryId.
	 * @param categoryId the categoryId to set.
	 */
	public void setCategoryId(final Long categoryId) {
		this.categoryId = categoryId;
	}

	/**
	 * Sets id.
	 * @param id the id to set.
	 */
	public void setId(final Long id) {
		this.id = id;
	}

	/**
	 * {@inheritDoc}
	 * @see com.google.code.sapien.interceptor.UserAware#setCurrentUser(User)
	 */
	public void setCurrentUser(final User currentUser) {
		this.currentUser = currentUser;
	}

	/**
	 * Sets page.
	 * @param page the page to set.
	 */
	public void setPage(final int page) {
		this.page = page;
	}

	/**
	 * Sets subject.
	 * @param subject the subject to set.
	 */
	public void setSubject(final String subject) {
		this.subject = subject;
	}
	
}
